package com.liu.concurrent.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 子线程循环3次,接着主线程循环5次,接着再子线程循环3次,主线程循环5次,如此反复,循环3次 方式二：使用 lock 锁和 Condition 接口
 *
 */
public class MyThread2 {
	private boolean flag = false;
	Lock lock = new ReentrantLock();
	Condition con = lock.newCondition();

	// 主线程要实现的功能
	public void mainFunction() {
		System.out.println("1.主线程开始" + " -- flag=" + flag);
		lock.lock();
		try {
			while (!flag) {
				try {
					System.out.println("2.主线程等待" + " -- flag=" + flag);
					con.await();
					// 使当前线程加入 await()
					// 等待队列中，并释放当锁，当其他线程调用signal()会重新请求锁。与Object.wait()类似。
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.println("7.主线程开始循环5次" + " -- flag=" + flag);
			for (int i = 0; i < 5; i++) {
				System.out.println("mainFunction" + i + " -- flag=" + flag);
			}
			flag = false;
			System.out.println("8.唤醒子线程" + " -- flag=" + flag);
			con.signal();
			// 唤醒一个在 await()等待队列中的线程。与Object.notify()相似
		} finally {
			lock.unlock();
		}
	}

	// 子线程要实现的功能
	public void subFunction() {
		System.out.println("3.子线程开始" + " -- flag=" + flag);
		lock.lock();
		try {
			while (flag) {
				try {
					System.out.println("6.子线程等待" + " -- flag=" + flag);
					con.await(); // 使当前线程加入 await()
									// 等待队列中，并释放当锁，当其他线程调用signal()会重新请求锁。与Object.wait()类似。
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.println("4.子线程开始循环3次" + " -- flag=" + flag);
			for (int i = 0; i < 3; i++) {
				System.out.println("subFunction" + i + " -- flag=" + flag);
			}
			flag = true;
			System.out.println("5.唤醒主线程" + " -- flag=" + flag);
			con.signal(); // 唤醒一个在 await()等待队列中的线程。与Object.notify()相似
		} finally {
			lock.unlock();
		}
	}

	public static void main(String[] args) {
		final MyThread2 t = new MyThread2();
		// 子线程循环三次
//		new ByExtendsThread(new Runnable() {
//			@Override
//			public void run() {
//				for (int i = 0; i < 3; i++) {
//					t.subFunction();
//					System.out.println("======");
//				}
//			}
//		}).start();
		// 主线程循环三次
		for (int i = 0; i < 3; i++) {
			t.mainFunction();
			System.out.println("======");
		}
	}
}
